package mianshi;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 
 *对多个java源文件进行解析，每个线程解析一个java文件
 */
public class Q4 {

	static int threadCount = 1;// 默认解析线程为1
	static Long whiteLines = 0L;
	static Long commentLines = 0L;
	static Long normalLines = 0L;
	static Long totalLines = 0L;
	static Integer fileCount = 0;
	static List<File> codeFiles = new ArrayList<File>();

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		threadCount = 5;// 设置解析线程的最大个数
		File f = new File("D:\\Work\\workspace\\inmsservice");// 指定需要解析的目录
		//获得当前目录下的所有java文件
		try {
			showAndSetAllFiles(f);
		} catch (Exception e) {
			e.printStackTrace();
		}
		fileCount = codeFiles.size();
		System.out.println("需要解析的java文件总数："+fileCount);
		
		System.out.println("\n各线程打印格式如下：");
		System.out.println("线程(索引)解析：文件路径    [总行数,空行数,注释行数,有效代码行数]\n");
		//启动解析线程
		if(fileCount<threadCount){
			threadCount=fileCount;
		}
		long startTime = System.currentTimeMillis();
		for(int i=0;i<threadCount;i++){
			startParseThread(i);
		}
		//解析完后打印结果
		while (true) {
			if (fileCount == 0) {
				System.out.println("总行数,空行数,注释行数,有效代码行数: [" +totalLines+","+ whiteLines+","+commentLines+","+normalLines+"]");
				break;
			}
		}
		System.out.println("用时："+(System.currentTimeMillis()-startTime)+"ms");
	}

	//递归把所有java文件放到集合中
	final static void showAndSetAllFiles(File dir) throws Exception {
		File[] fs = dir.listFiles();
		for (int i = 0; i < fs.length; i++) {
			if (fs[i].getName().matches(".*\\.java$")) {
				codeFiles.add(fs[i]);
			}
			if (fs[i].isDirectory()) {
				try {
					showAndSetAllFiles(fs[i]);
				} catch (Exception e) {
				}
			}
		}
	}

	//解析线程
	private static void startParseThread(final int index) {
		new Thread() {
			long currWhiteLines = 0;
			long currCommentLines = 0;
			long currNormalLines = 0;
			long currTotalLines = 0;
			public void run() {
				System.out.println("线程("+index+")启动。。。");
				while(fileCount>0){
					File file = null;
					synchronized (codeFiles) {
						if(codeFiles.size()>0){
							file=codeFiles.remove(codeFiles.size()-1);
						}
					}
					if(file!=null){
						parseFile(file);
						System.out.println("线程("+index+")解析："+file.getAbsolutePath()
								+"   [" +currTotalLines+","+ currWhiteLines+","+currCommentLines+","+currNormalLines+"]");
						synchronized (fileCount) {
							fileCount--;
						}
					}
				}
				System.out.println("线程("+index+")结束！！！");
			}

			private void parseFile(File file) {
				currWhiteLines = 0;
				currCommentLines = 0;
				currNormalLines = 0;
				currTotalLines = 0;
				BufferedReader br = null;
				boolean comment = false;
				try {
					br = new BufferedReader(new FileReader(file));
					String line = "";
					while ((line = br.readLine()) != null) {
						currTotalLines++;
						line = line.trim();
						if (line.matches("^[\\s&&[^\\n]]*$")) {
							currWhiteLines++;
						} else if (line.startsWith("/*")
								&& !line.endsWith("*/")) {
							currCommentLines++;
							comment = true;
						} else if (line.startsWith("/*") && line.endsWith("*/")) {
							currCommentLines++;
						} else if (true == comment) {
							currCommentLines++;
							if (line.endsWith("*/")) {
								comment = false;
							}
						} else if (line.startsWith("//")) {
							currCommentLines++;
						} else {
							currNormalLines++;
						}
					}
					synchronized (whiteLines) {
						whiteLines += currWhiteLines;
					}
					synchronized (commentLines) {
						commentLines += currCommentLines;
					}
					synchronized (normalLines) {
						normalLines += currNormalLines;
					}
					synchronized (totalLines) {
						totalLines += currTotalLines;
					}
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				} finally {
					if (br != null) {
						try {
							br.close();
							br = null;
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}
			}
		}.start();
	}

}
